package com.sergio.accounting.service.impl;

import com.sergio.accounting.entity.User;
import com.sergio.accounting.repository.UserRepository;
import com.sergio.accounting.service.UserService;
import com.sergio.accounting.util.JwtUtil;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.Optional;

/**
 * 用户服务实现类
 */
@Slf4j
@Service
@RequiredArgsConstructor
@Transactional
public class UserServiceImpl implements UserService {

    private final UserRepository userRepository;
    private final BCryptPasswordEncoder passwordEncoder;
    private final JwtUtil jwtUtil;

    @Override
    public User register(String username, String password, String email, String nickname) {
        // 检查用户名是否已存在
        if (existsByUsername(username)) {
            throw new RuntimeException("用户名已存在");
        }

        // 检查邮箱是否已存在
        if (email != null && existsByEmail(email)) {
            throw new RuntimeException("邮箱已被使用");
        }

        // 创建新用户
        User user = new User();
        user.setUsername(username);
        user.setPassword(passwordEncoder.encode(password));
        user.setEmail(email);
        user.setNickname(nickname != null ? nickname : username);
        user.setEnabled(true);
        user.setCreatedAt(LocalDateTime.now());

        User savedUser = userRepository.save(user);
        log.info("用户注册成功: {}", username);
        return savedUser;
    }

    @Override
    public String login(String username, String password) {
        Optional<User> userOpt = userRepository.findByUsername(username);
        if (!userOpt.isPresent()) {
            throw new RuntimeException("用户名或密码错误");
        }

        User user = userOpt.get();
        if (!user.getEnabled()) {
            throw new RuntimeException("账户已被禁用");
        }

        if (!passwordEncoder.matches(password, user.getPassword())) {
            throw new RuntimeException("用户名或密码错误");
        }

        // 更新最后登录时间
        user.setLastLoginAt(LocalDateTime.now());
        userRepository.save(user);

        // 生成JWT token
        String token = jwtUtil.generateToken(user);
        log.info("用户登录成功: {}", username);
        return token;
    }

    @Override
    @Transactional(readOnly = true)
    public User findById(Long id) {
        return userRepository.findById(id)
                .orElseThrow(() -> new RuntimeException("用户不存在"));
    }

    @Override
    @Transactional(readOnly = true)
    public User findByUsername(String username) {
        return userRepository.findByUsername(username)
                .orElseThrow(() -> new RuntimeException("用户不存在"));
    }

    @Override
    public User updateUser(Long id, String nickname, String email, String avatar) {
        User user = findById(id);

        // 检查邮箱是否被其他用户使用
        if (email != null && !email.equals(user.getEmail())) {
            if (existsByEmail(email)) {
                throw new RuntimeException("邮箱已被其他用户使用");
            }
            user.setEmail(email);
        }

        if (nickname != null) {
            user.setNickname(nickname);
        }

        if (avatar != null) {
            user.setAvatar(avatar);
        }

        user.setUpdatedAt(LocalDateTime.now());
        User updatedUser = userRepository.save(user);
        log.info("用户信息更新成功: {}", user.getUsername());
        return updatedUser;
    }

    @Override
    public User updateDetailedProfile(Long id, com.sergio.accounting.dto.UserProfileUpdateRequest request) {
        User user = findById(id);

        // 检查邮箱是否被其他用户使用
        if (request.getEmail() != null && !request.getEmail().equals(user.getEmail())) {
            if (existsByEmail(request.getEmail())) {
                throw new RuntimeException("邮箱已被其他用户使用");
            }
            user.setEmail(request.getEmail());
        }

        // 更新基本信息
        if (request.getName() != null) {
            user.setNickname(request.getName());
        }

        if (request.getDesc() != null) {
            user.setDescription(request.getDesc());
        }

        // 处理头像：如果有avatarUrl则使用图片头像，否则使用emoji头像
        if (request.getAvatarUrl() != null && !request.getAvatarUrl().isEmpty()) {
            user.setAvatar(request.getAvatarUrl());
        } else if (request.getAvatarText() != null && !request.getAvatarText().isEmpty()) {
            // 如果设置了emoji头像，清空图片头像，将emoji作为头像标识符
            user.setAvatar(request.getAvatarText());
        }

        if (request.getPhone() != null) {
            user.setPhone(request.getPhone());
        }

        // 处理标签（将List转换为逗号分隔的字符串）
        if (request.getTags() != null && !request.getTags().isEmpty()) {
            String tagsString = String.join(",", request.getTags());
            user.setTags(tagsString);
        }

        user.setUpdatedAt(LocalDateTime.now());
        User updatedUser = userRepository.save(user);
        log.info("用户详细信息更新成功: {}", user.getUsername());
        return updatedUser;
    }

    @Override
    public boolean changePassword(Long userId, String oldPassword, String newPassword) {
        User user = findById(userId);

        if (!passwordEncoder.matches(oldPassword, user.getPassword())) {
            throw new RuntimeException("原密码错误");
        }

        user.setPassword(passwordEncoder.encode(newPassword));
        user.setUpdatedAt(LocalDateTime.now());
        userRepository.save(user);

        log.info("用户密码修改成功: {}", user.getUsername());
        return true;
    }

    @Override
    @Transactional(readOnly = true)
    public boolean existsByUsername(String username) {
        return userRepository.existsByUsername(username);
    }

    @Override
    @Transactional(readOnly = true)
    public boolean existsByEmail(String email) {
        return userRepository.existsByEmail(email);
    }

    @Override
    public String refreshToken(String token) {
        try {
            // 验证原token
            String username = jwtUtil.extractUsername(token);
            if (username == null || !jwtUtil.validateToken(token, username)) {
                throw new RuntimeException("无效的token");
            }
            
            // 生成新token
            User user = findByUsername(username);
            String newToken = jwtUtil.generateToken(user);
            
            log.info("用户token刷新成功: {}", username);
            return newToken;
        } catch (Exception e) {
            log.error("token刷新失败: {}", e.getMessage());
            throw new RuntimeException("token刷新失败");
        }
    }
}
